package cn.com.zonesion.rfiddemo.activity;

import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTransaction;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.RadioGroup;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import com.x210.android.serialPortSample.SerialPort;
import com.x210.android.serialPortSample.SerialPortFinder;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.TimeZone;

import butterknife.BindView;
import butterknife.ButterKnife;
import cn.com.zonesion.rfiddemo.R;
import cn.com.zonesion.rfiddemo.adapter.CardRelateInfoAdapter;
import cn.com.zonesion.rfiddemo.adapter.InstructionListAdapter;
import cn.com.zonesion.rfiddemo.base.BaseFragment;
import cn.com.zonesion.rfiddemo.bean.CardRelateBean;
import cn.com.zonesion.rfiddemo.bean.InstructionBean;
import cn.com.zonesion.rfiddemo.fragment.icfragment.IcApplicationFragment;
import cn.com.zonesion.rfiddemo.fragment.icfragment.IcBasicsFragment;
import cn.com.zonesion.rfiddemo.fragment.icfragment.IcCardPurseFragment;

/**
 * Created by Administrator on 2018/4/23.
 */

public class ICMainActivity extends FragmentActivity implements View.OnClickListener{
    /**
     * 该视图用来替换成要切换的页面
     */
    @BindView(R.id.content_fragment_ic)
    FrameLayout ContentFragmentIc;

    @BindView(R.id.rg_bottom_tag)
    RadioGroup rgBottomTag;
    /**
     * 标识是否串口链接成功
     */
    @BindView(R.id.image_link_icon_ic)
    ImageView imageLinkIconIc;
    /**
     * 展示当前系统时间
     */
    @BindView(R.id.tv_current_time_ic)
    TextView tvCurrentTimeIc;
    /**
     *  该按钮用来连接和断开串口
     */
    @BindView(R.id.btn_connection_ic)
    Button  btnConneCtionIc;
    @BindView(R.id.listView_debugging_ic)
    ListView listViewDebuggingIc;
    /**
     * 开启滑动
     */
    @BindView(R.id.btn_slide_data_ic)
    Button btnSlideDataIc;
    /**
     * 装多个Fragment的实例集合
     */
    private ArrayList<BaseFragment> fragments;
    private int position = 0;
    /**
     * 缓存的Fragemnt或者上次显示的Fragment
     */
    private Fragment tempFragemnt;

    private static final int msgKey1 = 1;
    /**
     * 波特率数组，用来存放常用波特率
     */
    private String[] baudrateArray;
    /**
     * 存放串口路径的ArrayList
     */
    private ArrayList<String> deviceList;

    /**
     * 该ArrayList用来存放InstructionBean对象
     */
    private ArrayList<InstructionBean> instructionList;
    /**
     * 该ArrayList用来存放CardRelateBean对象
     */
    private ArrayList<CardRelateBean> cardRelateList;

    /**
     * listInstruction的适配器对象
     */
    private InstructionListAdapter listAdapter;
    private CardRelateInfoAdapter cardRelateInfoAdapter;

    /**
     * MainHandler用来发送消息
     */
    private MainHandler mainHandler;
    /**
     * 通过MainHandler发送消息检测当前可用串口的标识
     */
    private static final int CHECK_SERIAL = 0;
    /**
     * 通过MainHandler发送消息查询卡号的标识
     */
    private static final int QUERY_CARD_NUM = 1;
    /**
     * 通过MainHandler发送消息定时清空卡号和余额的标识
     */
    private static final int CLEAR_DATA = 2;
    /**
     * 记录无卡指令出现的次数
     */
    private static int NO_CARD = 0;
    /**
     * 串口对象
     */
    private SerialPort serialPort;

    /**
     * 该字符串表示当前用户使用的串口路径
     */
    private String serialPath;

    /**
     * 表示当前用户使用的波特率
     */
    private int baudRate;

    /**
     * 用来标识是否已经开启了读取数据的线程
     */
    private boolean hasStartedThread = false;
    /**
     * 用来标识是否已经提示用户串口连接成功
     */
    private boolean hasTipConnection = false;
    /**
     * 该线程用来读取串口返回来的数据
     */
    private Thread readThread;

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage (Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case msgKey1:
                    tvCurrentTimeIc.setText(getTime());
                    break;
                default:
                    break;
            }
        }
    };

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main_ic);
        //ButterKnife和当前Activity绑定
        ButterKnife.bind(this);
        /**
         * 初始化Fragment
         */
        initFragment();
        //设置RadioGroup的监听
        initListener();
        initView();
        mainHandler.sendEmptyMessage(CHECK_SERIAL);
    }

    private void initListener(){
        rgBottomTag.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                switch (checkedId) {
                    case  R.id.btn_basics_ic://基础
                        position = 0;
                        break;
                    case  R.id.btn_card_purse_ic://卡钱包
                        position = 1;
                        break;
                    case  R.id.btn_application_ic://应用
                        position = 2;
                        break;
                    default:
                        position = 0;
                        break;

                }
                //根据位置取不同的Fragment
                BaseFragment baseFragment = getFragment(position);
                switchFragment(tempFragemnt, baseFragment);
            }
        });
        rgBottomTag.check(R.id.btn_basics_ic);
    }
    /**
     * 添加的时候要按照顺序
     */
    private void initFragment() {
        fragments = new ArrayList<>();
        fragments.add(new IcBasicsFragment());
        fragments.add(new IcCardPurseFragment());
        fragments.add(new IcApplicationFragment());
    }
    private BaseFragment getFragment(int position) {
        if (fragments != null && fragments.size() > 0) {
            BaseFragment baseFragment = fragments.get(position);
            return baseFragment;
        }
        return null;
    }
    /**
     * 切换Fragment
     * @param fromFragment
     * @param nextFragment
     */
    private void switchFragment(Fragment fromFragment, BaseFragment nextFragment) {
        if (tempFragemnt != nextFragment) {
            tempFragemnt = nextFragment;
            if (nextFragment != null) {
                FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
                //判断nextFragment是否添加
                if (!nextFragment.isAdded()) {
                    //隐藏当前Fragment
                    if (fromFragment != null) {
                        transaction.hide(fromFragment);
                    }
                    //添加Fragment
                    transaction.add(R.id.content_fragment_ic, nextFragment).commit();
                } else {
                    //隐藏当前Fragment
                    if (fromFragment != null) {
                        transaction.hide(fromFragment);
                    }
                    transaction.show(nextFragment).commit();
                }
            }
        }
    }
    private void initView() {
        new TimeThread().start();
        mainHandler = new MainHandler(this);
        baudrateArray =getResources().getStringArray(R.array.baudrate);
        deviceList = new ArrayList<>();
        instructionList = new ArrayList<>();
        cardRelateList = new ArrayList<>();
        listAdapter = new InstructionListAdapter(this,instructionList);
        cardRelateInfoAdapter = new CardRelateInfoAdapter(this,cardRelateList);
        listViewDebuggingIc.setAdapter(listAdapter);
//        listAboutCard.setAdapter(cardRelateInfoAdapter);
        btnConneCtionIc.setOnClickListener(this);
        btnSlideDataIc.setOnClickListener(this);
    }

    @Override
    protected void onDestroy() {
        mainHandler.removeCallbacksAndMessages(null);//当Activity销毁的时候，移除所有消息和回调
        super.onDestroy();
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case  R.id.btn_connection_ic:
                btnConnectSerialClickEvent();
                break;
            case R.id.btn_slide_data_ic:
                btnInstructionSlideClickEvent();
                break;
        }
    }
    private void showOpenTheSerialPort(String title){
        View view = View.inflate(ICMainActivity.this,R.layout.activity_seria_iport_picker,null);
        //找到布局文件中的控件
        final Spinner ttySpinner = view.findViewById(R.id.tty_spinner);
        final Spinner ttyBaudrate = view.findViewById(R.id.tty_baudrate);
        ttySpinner.setAdapter(new ArrayAdapter<>(getApplicationContext(),R.layout.spinner_layout,R.id.textView,deviceList));
        ttyBaudrate.setAdapter(new ArrayAdapter<>(getApplicationContext(),R.layout.spinner_layout,R.id.textView,baudrateArray));
        new Thread(new Runnable() {//开启一个线程获取可用串口的路径
            @Override
            public void run() {
                String[] devicesPath = new SerialPortFinder().getAllDevicesPath();
                deviceList.addAll(Arrays.asList(devicesPath));
            }
        }).start();
        //为ttySpinner注册监听事件
        ttySpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> adapterView, View view, int position, long id) {
                serialPath = deviceList.get(position);//如果Spinner被选中的一项下标不为0，则得到该项字符串内容并赋值
            }

            @Override
            public void onNothingSelected(AdapterView<?> adapterView) {}
        });
        //为ttyBaudrate注册监听事件
        ttyBaudrate.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> adapterView, View view, int position, long id) {
                baudRate = Integer.parseInt(baudrateArray[position]);
            }

            @Override
            public void onNothingSelected(AdapterView<?> adapterView) {}
        });
        new AlertDialog.Builder(this)
                    .setTitle(title)
                    .setView(view)
                    .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            if(serialPort == null){
                                try {
                                    serialPort = new SerialPort(new File(serialPath),baudRate);
                                    btnConneCtionIc.setText("关闭串口");
                                    if(!hasStartedThread) {
                                        if(readThread == null) {
                                            hasStartedThread = true;//将hasStartedThread设置为true 表示线程已启动 防止线程多次启动带来的巨大开销
                                            readThread = new Thread(new ReadThread());
                                            readThread.start();//启动线程
                                        }
                                    }
                                    mainHandler.sendEmptyMessage(QUERY_CARD_NUM);//发送消息查询125K卡号
                                } catch (IOException e) {
                                    e.printStackTrace();
                                    Toast.makeText(getApplicationContext(), "串口对象创建异常，请检查串口或波特率是否正确,并重新连接", Toast.LENGTH_SHORT).show();
                                    //出现异常后将serialPort设置为null 将hasStartedThread设置为false 将按钮文本设置为"连接串口" 以便可以重新连接串口和开启读取数据的线程
                                    btnConneCtionIc.setText("连接串口");
                                    serialPort = null;
                                    hasStartedThread = false;
                                }
                            }
                        }
                    })
                    .setNegativeButton("取消", null)
                    .show();

    }
    /**
     * btnInstructionSlide按钮的单击事件响应对应的方法
     */
    private void btnInstructionSlideClickEvent(){
        if(btnSlideDataIc.getText().toString().equals("停止滑动数据")){
            btnSlideDataIc.setText("开启滑动数据");
        } else if(btnSlideDataIc.getText().toString().equals("开启滑动数据")){
            btnSlideDataIc.setText("停止滑动数据");
        }
    }

    /**
     * btnConnectSerial按钮的单击事件响应对应的方法
     */
    private void btnConnectSerialClickEvent(){
        if(btnConneCtionIc.getText().toString().equals("连接串口")){
//            if(serailSpinner.getSelectedItemPosition() == 0){//如果serailSpinner选中的是第一项，代表没有选择串口路径
//                Toast.makeText(getApplicationContext(), "请选择串口", Toast.LENGTH_SHORT).show();
//                return;
//            }
            showOpenTheSerialPort("串口设置");
        }else if(btnConneCtionIc.getText().toString().equals("关闭串口")){
            btnConneCtionIc.setText("连接串口");
            Thread t = new Thread(){
                public void run(){
                    if (serialPort != null) {
                        hasStartedThread = false;
                        if (readThread != null) {
                            try {
                                readThread.join();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            readThread = null;
                        }
                        serialPort.close();//调用close方法关闭串口
                        serialPort = null;
                    }
                }
            };
            t.start();
        }
    }

    public class TimeThread extends Thread {
        @Override
        public void run () {
            do {
                try {
                    Thread.sleep(1000);
                    Message msg = new Message();
                    msg.what = msgKey1;
                    mHandler.sendMessage(msg);
                }
                catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } while(true);
        }
    }
    /**
     * /获得当前年月日时分秒星期
     * @return
     */
    public String getTime(){
        final Calendar c = Calendar.getInstance();
        c.setTimeZone(TimeZone.getTimeZone("GMT+8:00"));
        String mYear = String.valueOf(c.get(Calendar.YEAR)); // 获取当前年份
        String mMonth = String.valueOf(c.get(Calendar.MONTH) + 1);// 获取当前月份
        String mDay = String.valueOf(c.get(Calendar.DAY_OF_MONTH));// 获取当前月份的日期号码
        String mWay = String.valueOf(c.get(Calendar.DAY_OF_WEEK));
        String mHour = String.valueOf(c.get(Calendar.HOUR_OF_DAY));//时
        String mMinute = String.valueOf(c.get(Calendar.MINUTE));//分
        String mSecond = String.valueOf(c.get(Calendar.SECOND));//秒
        if("1".equals(mWay)){
            mWay ="天";
        }else if("2".equals(mWay)){
            mWay ="一";
        }else if("3".equals(mWay)){
            mWay ="二";
        }else if("4".equals(mWay)){
            mWay ="三";
        }else if("5".equals(mWay)){
            mWay ="四";
        }else if("6".equals(mWay)){
            mWay ="五";
        }else if("7".equals(mWay)){
            mWay ="六";
        }
        return mYear + "年" + mMonth + "月" + mDay+"日"+" "+"星期"+mWay+" "+mHour+":"+mMinute+":"+mSecond;
    }
    //该方法用来查询13.56M的卡号
    private void query13Dot56MCardNo() {
        if (serialPort != null) {
            OutputStream outputStream = serialPort.getOutputStream();
            try {
                byte[] dat = new byte[]{(byte) 0xab, (byte) 0xba, 0x00, 0x10, 0x00, 0x10};
                outputStream.write(dat);
                outputStream.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    /**
     * bytes转换成十六进制字符串
     * @param b byte数组
     * @return String 每个Byte值之间空格分隔
     */
    public static String byte2HexStr(byte[] b)
    {
        String stmp="";
        StringBuilder sb = new StringBuilder("");
        for (int n=0;n<b.length;n++)
        {
            stmp = Integer.toHexString(b[n] & 0xFF);
            sb.append((stmp.length()==1)? "0"+stmp : stmp);
            sb.append(" ");
        }
        return sb.toString().toUpperCase().trim();
    }
    /**
     * 该方法用于更新界面底部的指令展示
     * @param instruction 指令的名称
     * @param role 指令的作用
     */
    private void updateInstructionData(String instruction,String role){
        instructionList.add(new InstructionBean(instruction,role));
        listAdapter.notifyDataSetChanged();//更新ListView数据
        if(btnSlideDataIc.getText().toString().equals("停止滑动数据")){
            listViewDebuggingIc.setSelection(listViewDebuggingIc.getCount() - 1);
        }
        if(btnSlideDataIc.getText().toString().equals("开启滑动数据")){
            listViewDebuggingIc.setSelection(-1);
        }
    }
    /**
     * 该线程用来读取数据
     */
    private class ReadThread implements Runnable{

        @Override
        public void run() {
            String str;
            InputStream inputStream = serialPort.getInputStream();
            byte[] receive = new byte[25];
            try {
                int ret = 0, offset = 0;
                while (hasStartedThread && (ret = inputStream.read(receive, offset, 25 - offset)) != -1) {
                    offset += ret;
                    if ((receive[0] & 0xff) == 0xCD && (receive[1] & 0xff) == 0xDC) {
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                if(!hasTipConnection) {
                                    Toast.makeText(getApplicationContext(), "串口连接成功", Toast.LENGTH_SHORT).show();
                                    hasTipConnection = true;
                                }
                            }
                        });
                        if (offset > 5) {
                            int pkglen = receive[4] + 6;
                            if (pkglen <= offset) {
                                if (pkglen > 0) {
                                    byte[] pkg = new byte[pkglen];
                                    System.arraycopy(receive, 0, pkg, 0, pkglen);
                                    str = ICMainActivity.byte2HexStr(pkg);
                                    String[] result = str.split(" ");
                                    final String finalStr = str;
                                    if (result.length == 10) {
                                        runOnUiThread(new Runnable() {
                                            @Override
                                            public void run() {
                                                updateInstructionData("串口<<--: " + finalStr,"有13.56M的卡刷卡");
                                            }
                                        });

                                        ICMainActivity.NO_CARD = 0;//清0，表示有卡
                                        final String card = result[5] + result[6] + result[7] + result[8];
                                        runOnUiThread(new Runnable() {
                                            @Override
                                            public void run() {
//                                                textCardNo.setText(card);
                                            }
                                        });

                                    }else {
                                        runOnUiThread(new Runnable() {
                                            @Override
                                            public void run() {
                                                updateInstructionData("串口<<--: " + finalStr,"无卡");
                                            }
                                        });

                                        ICMainActivity.NO_CARD  += 1;
                                    }

                                    if(ICMainActivity.NO_CARD >= 8){
                                        mainHandler.sendEmptyMessage(CLEAR_DATA);//如果无卡指令连续出现等于或超过8次，发送消息，清空用户名和卡号
                                    }
                                    System.out.println(str);
                                    int left = offset - pkglen;
                                    if (left > 0) {
                                        System.arraycopy(receive, pkglen, receive, 0, left);
                                    }
                                    offset = left;
                                }
                            }
                        }
                    } else {
                        offset = 0;
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
                hasStartedThread = false;
            }
        }
    }
    private static class MainHandler extends Handler{
        private WeakReference<ICMainActivity> reference;

        MainHandler(ICMainActivity mainActivity){
            reference = new WeakReference<>(mainActivity);
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what){
                case ICMainActivity.CHECK_SERIAL:
                    if(reference.get()!=null) {
                        String[] driverVector = new SerialPortFinder().getAllDevicesPath();
                        reference.get().deviceList.clear();
                        reference.get().deviceList.add("请选择串口：");
                        reference.get().deviceList.addAll(Arrays.asList(driverVector));
//                        ((BaseAdapter)reference.get().serailSpinner.getAdapter()).notifyDataSetChanged();
                    }
//                    removeMessages(ICMainActivity.CHECK_SERIAL);
//                    sendEmptyMessageDelayed(ICMainActivity.CHECK_SERIAL,3000);
                    break;
                case ICMainActivity.QUERY_CARD_NUM:
                    if(reference.get() != null){
                        reference.get().query13Dot56MCardNo();
                        byte[] dat1 = new byte[]{(byte) 0xab, (byte) 0xba, 0x00, 0x10, 0x00, 0x10};
                        reference.get().updateInstructionData("串口主动发出-->> " + ICMainActivity.byte2HexStr(dat1),"查询13.56M类型卡的卡号");
                    }
                    removeMessages(ICMainActivity.QUERY_CARD_NUM);//先移除消息
                    sendEmptyMessageDelayed(ICMainActivity.QUERY_CARD_NUM,500);//每500毫秒查询一次卡号
                    break;
            }
        }
    }
}
